package cn.gailvlun.gll.net.token

import cn.gailvlun.gll.net.GsonUtil
import cn.gailvlun.gll.net.interceptor.AUTH
import cn.gailvlun.gll.net.interceptor.DETAIL
import cn.gailvlun.gll.util.IsEmpty
import cn.gailvlun.gll.util.ProfileUtil
import okhttp3.Interceptor
import okhttp3.Response
import java.net.HttpURLConnection
import java.nio.charset.Charset


enum class TokenStateEnum {
    
    NONE,
    UNAUTHORIZED,
    OTHERS;

    data class TokeState(var stateEnum: TokenStateEnum,
                         var response: Response?)

    companion object {
        private val UTF8 = Charset.forName("UTF-8")
        fun getTokenState(chain: Interceptor.Chain): TokeState {
            val token = getToken()
            return if (IsEmpty.string(token)) {
                TokeState(NONE, null)
            } else {
                val request = chain.request()
                        .newBuilder()
                        .addHeader(AUTH, token)
                        .build()
                val response = chain.proceed(request)

                if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED && getTokenExpiredDetail(response) == DETAIL) {
                    TokeState(UNAUTHORIZED, response)
                } else {
                    TokeState(OTHERS, response)
                }
            }
        }

        
        fun getToken(): String {
            val dbToken = ProfileUtil.getToken()
            return "JWT $dbToken"
        }


        private fun getTokenExpiredDetail(response: Response): String {
            if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) {
                val responseBody = response.body()
                val source = responseBody?.source()
                source?.request(Long.MAX_VALUE)
                val buffer = source?.buffer()
                var charset = UTF8
                val contentType = responseBody?.contentType();
                if (contentType != null) charset = contentType.charset(UTF8)
                val string = buffer?.clone()?.readString(charset)
                return GsonUtil.getGson().fromJson<cn.gailvlun.gll.net.Response>(string, cn.gailvlun.gll.net.Response::class.java).detail
            }
            return ""
        }
    }
}